<template>
  <div class="container">
    <h3>vue+openlayers: 绘制矩形，显示首尾点和中心点的坐标值，同时获取所有点的经纬度</h3>
    <h4>
      <el-button type="primary" size="mini" @click="drawPolygon('Rectangle')">绘制矩形</el-button>
    </h4>
    <div id="vue-openlayers"></div>
    <div id="coordinateInfo" v-show="isShowInfo"></div>
  </div>
</template>

<script>
import 'ol/ol.css';
import { Map, View } from 'ol';
import Tile from 'ol/layer/Tile';
import XYZ from 'ol/source/XYZ';
import LayerVector from 'ol/layer/Vector';
import SourceVector from 'ol/source/Vector';
import Feature from 'ol/Feature';  // 用来创建要素
import Fill from 'ol/style/Fill'; // 用来创建填充样式
import Stroke from 'ol/style/Stroke'; // 用来创建边线样式
import Style from 'ol/style/Style'; // 用来创建样式
import Text from 'ol/style/Text'; // 用来创建文本样式
import Circle from 'ol/style/Circle'; // 用来创建圆形样式
import Draw, { createBox } from 'ol/interaction/Draw'; // 用来创建绘制交互
import MultiPoint from 'ol/geom/MultiPoint'; // 用来创建多点
import { getCenter } from 'ol/extent'; // 用来获取范围的中心点
import { Point } from 'ol/geom'; // 用来创建点;
export default {
  data() {
    return {
      map: null,
      draw: null,
      source: new SourceVector({
        wrapX: false // 不允许x轴方向重复
      }),
      pointSource: new SourceVector({
        wrapX: false // 不允许x轴方向重复
      }),
      isShowInfo: false,
    }
  },
  mounted() {
    this.initMap();
  },
  methods: {
    initMap() {
      let layer = new Tile({
        source: new XYZ({
          url: 'http://wprd0{1-4}.is.autonavi.com/appmaptile?x={x}&y={y}&z={z}&lang=zh_cn&size=1&scl=1&style=7'
        })
      })
      let drawLayer = new LayerVector({
        source: this.source,
        style: [
          new Style({
            fill: new Fill({
              color: 'transparent'
            }),
            stroke: new Stroke({
              color: '#ffcc33',
              width: 2
            })
          }),
          new Style({
            image: new Circle({
              radius: 5,
              fill: new Fill({
                color: 'red'
              }),
              stroke: new Stroke({
                color: 'orange',
                width: 2
              })
            }),
            geometry: function(feature) {
              var coordinates = feature.getGeometry().getCoordinates()[0]; // 获取绘制的坐标
              return new MultiPoint(coordinates);
            }
          })
        ]
      })
      this.map = new Map({
        target: 'vue-openlayers',
        layers: [layer, drawLayer],
        view: new View({
          center: [116.397411, 39.909186],
          zoom: 7,
          projection: 'EPSG:4326'
        })
      })
    },

    // 点样式
    pointStyle(text) {
      let style = new Style({
        image: new Circle({ // 圆形样式
          radius: 7,
          fill: new Fill({
            color: '#ffcc33'
          })
        }),
        text: new Text({
          font: '12px Roboto', // 字体
          maxAngle: 30, // 文本最大倾斜角度
          offsetX: 50, // 文本X轴偏移量
          offsetY: 20, // 文本Y轴偏移量
          text: text, // 文本内容
          fill: new Fill({
            color: '#F0F',
          }),
          backgroundFill: new Fill({
            color: 'rgba(255, 255, 255, 0.6)',
          }),
        })
      })
      return style;
    },

    // 显示点信息
    showPoint(coord, text) {
      let pointFeature = new Feature({ // 创建点要素
        geometry: new Point(coord)
      })
      pointFeature.setStyle(this.pointStyle(text)) // 设置点样式
      this.pointSource.addFeature(pointFeature) // 添加到矢量数据源
      let pointLayer = new LayerVector({
        source: this.pointSource
      })
      this.map.addLayer(pointLayer)
    },

    // 格式化坐标数据
    numfixed2(array) {
      let a1 = (array[0] *  1).toFixed(2);
      let a2 = (array[1] *  1).toFixed(2);
      return [Number(a1), Number(a2)]
    },

    drawPolygon(x) {
      // 清除资源，只留一个图形
      this.source.clear();
      // 停止上一次绘制，没有此代码会出现重叠
      if (this.draw) {
        this.map.removeInteraction(this.draw);
      }
      let type = 'Circle';
      let geometryFunction = createBox();
      this.draw = new Draw({
        source: this.source,
        type,
        geometryFunction
      })
      this.map.addInteraction(this.draw);
      this.draw.on('drawstrat', e => { // 开始绘制
        this.isShowInfo = false;
      })
      const infobox = document.getElementById('coordinateInfo');
      this.draw.on('drawend', e => { // 绘制结束
        this.isShowInfo = true;
        let feature = e.feature; // 获取绘制要素
        let geom = feature.getGeometry(); // 获取要素几何信息
        let f = this.numfixed2(geom.getCoordinates()); // 获取要素坐标
        let i1 = JSON.stringify(f)
        let i2 = JSON.stringify(geom.getCoordinates()[0])
        let c = this.numfixed2(new getCenter(geom.getExtent())); // 获取要素中心点坐标
        let i3 = JSON.stringify(c)
        this.showPoint(f, i1)
        this.showPoint(c, i3)
        infobox.innerHTML = `坐标：${i1} <br> 中心点坐标：${i3} <br> 坐标点：${i2}`
        this.map.removeInteraction(this.draw);
      })
    }
  }
}
</script>

<style lang="scss" scoped>
.container {
    width: 100%;
    height: 750px;
    margin: 50px auto;
    border: 1px solid #ccc;
    #vue-openlayers {
      width: 100%;
      height: 720px;
      margin: 0 auto;
      border: 1px solid #42b983;
      position: relative;
    }
  }
</style>
